package com.aidisp.util;

/**
 * 
 * @author Z.x.Y
 * 经纬度公共类
 */
public class LatLng {
	// 赤道半径 earth radius
	public final double EARTH_RADIUS = 6378.137;
	// 极半径polar radius
	public final double POLAR_RADIUS = 6356.725;
	private double lat;
	private double lng;
	
	public double getLat() {
		return lat;
	}
	public void setLat(double lat) {
		this.lat = lat;
	}
	public double getLng() {
		return lng;
	}
	public void setLng(double lng) {
		this.lng = lng;
	}
	
	public LatLng(double lat, double lng) {
		this.lat = lat;
		this.lng = lng;
	}
	
	public double getRadLng() {
		return this.lng * Math.PI / 180;
	}

	public double getRadLat() {
		return this.lat * Math.PI / 180;
	}

	public double getEc() {
		return POLAR_RADIUS*1000 + (EARTH_RADIUS*1000 - POLAR_RADIUS*1000) * (90 - lat)
				/ 90;
	}

	public double getEd() {
		return getEc() * Math.cos(getRadLat());
	}
	@Override
	public String toString() {
		return this.lat+","+this.lng;
	}
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		long temp;
		temp = Double.doubleToLongBits(lat);
		result = prime * result + (int) (temp ^ (temp >>> 32));
		temp = Double.doubleToLongBits(lng);
		result = prime * result + (int) (temp ^ (temp >>> 32));
		return result;
	}
	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		LatLng other = (LatLng) obj;
		if (Double.doubleToLongBits(lat) != Double
				.doubleToLongBits(other.lat))
			return false;
		if (Double.doubleToLongBits(lng) != Double
				.doubleToLongBits(other.lng))
			return false;
		return true;
	}
	/**
	 * 计算经纬度两点之间的直线距离
	 * @param latLng
	 * @return
	 */
	public double calculateDistance(LatLng latLng) {
		double thisLatRad = this.getRadLat();
		double pointLatRad = latLng.getRadLat();
		double thisLngRad = this.getRadLng();
		double pointLngRad = latLng.getRadLng();
		
		double latDistance = thisLatRad - pointLatRad;
		double lngDistance = thisLngRad - pointLngRad;
		
		double distance = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(latDistance / 2), 2)
				+ Math.cos(thisLatRad) * Math.cos(pointLatRad)
				* Math.pow(Math.sin(lngDistance / 2), 2)));
		distance = distance * EARTH_RADIUS;
//		distance = Math.round(distance*10000)/10000;
		return distance;
	}
	/**
	 * 计算经纬度两点的正北角度
	 * @param latLng
	 * @return
	 */
	public int calculateAngle(LatLng latLng){
		double dx = (latLng.getRadLng() - this.getRadLng()) * this.getEd();
		double dy = (latLng.getRadLat() - this.getRadLat()) * this.getEc();
		int angle = (int)(Math.atan(Math.abs(dx / dy)) * 180. / Math.PI);
		double dLo = latLng.lng - this.lng;
		double dLa = latLng.lat - this.lat;
		
		if (dLo > 0 && dLa <= 0) {
			angle = (90 - angle) + 90;
		} else if (dLo <= 0 && dLa < 0) {
			angle = angle + 180;
		} else if (dLo < 0 && dLa >= 0) {
			angle = (90 - angle) + 270;
		}
		return angle;
	}
	/**
	 * 根据相对当前坐标的角度和距离计算下一点的经纬度坐标
	 * @param angle
	 * @param distance
	 * @return
	 */
	public LatLng calculateNextLatLng(int angle,double distance){
		double dx = distance * 1000 * Math.sin(angle * Math.PI / 180);
		double dy = distance * 1000 * Math.cos(angle * Math.PI / 180);
		double nextLng = (dx / this.getEd() + this.getRadLng()) * 180 / Math.PI;
		double nextLat = (dy / this.getEc() + this.getRadLat()) * 180 / Math.PI;
		return new LatLng(nextLat,nextLng);
	}
}